/*

This file is part of Rooms3D.

Copyright (C) 2008 Pixecur Technologies Incorporated (Esotera).
Visit Esotera at http://www.esoteras3.com
 
Rooms3D is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3, or (at your option)
any later version.
 
Rooms3D is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
General Public License for more details.
 
You should have received a copy of the GNU General Public License
along with Rooms3D; see the file COPYING.  If not, write to 
Pixecur Technologies, 213-31 Peet Street, St. John's, NL, A1B 3W8. 
 
Linking this library statically or dynamically with other modules is
making a combined work based on this library.  Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
 
*/

package com.datasentinel.rooms.ui.sh3d;

import java.util.ArrayList;
import java.util.List;
import java.util.logging.Logger;

import javax.swing.JComponent;
import javax.swing.undo.UndoableEditSupport;

import com.datasentinel.rooms.util.sh3d.CollisionUtils;
import com.eteks.sweethome3d.model.Home;
import com.eteks.sweethome3d.model.HomePieceOfFurniture;
import com.eteks.sweethome3d.model.PieceOfFurniture;
import com.eteks.sweethome3d.model.UserPreferences;
import com.eteks.sweethome3d.swing.HomeController3D;

public class CustomHomeController3D extends HomeController3D
{
	private static Logger logger = Logger
			.getLogger(CustomHomeController3D.class.getName());
	private Home home;
	private List<DoorCollisionListener> doorCollisionListeners;

	public CustomHomeController3D(Home home, UserPreferences preferences,
			UndoableEditSupport undoSupport)
	{
		super(home, preferences, undoSupport);
		this.home = home;
		doorCollisionListeners = new ArrayList<DoorCollisionListener>();
	}

	/**
	 * 
	 * tests for collision on camera move
	 * 
	 * reverses the move if collision is detected
	 */
	@Override
	public void moveCamera(float delta)
	{
		super.moveCamera(delta);
		HomePieceOfFurniture piece = CollisionUtils.testForIntersectionWithPieces(home.getFurniture(), home.getCamera());
		if(piece != null && piece.isDoorOrWindow() && 0 == piece.getElevation())
		{
			fireDoorCollision(piece);
		}	
		else if (CollisionUtils.testForIntersectionWithWalls(home.getWalls(),home.getCamera()))
		{
			super.moveCamera(-1 * delta);
		}
	}
	
	@Override
	public void rotateCameraPitch(float delta)
	{
		super.rotateCameraPitch(delta);
	}
	
	@Override
	public void rotateCameraYaw(float delta)
	{
		super.rotateCameraYaw(delta);
	}

	/**
	 * 
	 * controller must return the appropriate component
	 * 
	 * @see CustomHomeComponent3D
	 */
	@Override
	protected JComponent createHomeComponent3D(Home home)
	{
		return new CustomHomeComponent3D(home, this);
	}

	public void fireDoorCollision(PieceOfFurniture door)
	{
		synchronized (doorCollisionListeners)
		{
			for (DoorCollisionListener listener : doorCollisionListeners)
			{
				listener.collidedWith(door);
			}
		}
	}

	public void addDoorCollisionListener(DoorCollisionListener listener)
	{
		if (!doorCollisionListeners.contains(listener))
			doorCollisionListeners.add(listener);
		logger.warning("adding DoorCollisionListener = " + listener + ", count = [" + doorCollisionListeners.size() + "]");
	}

	public void removeDoorCollisionListener(DoorCollisionListener listener)
	{
		if (doorCollisionListeners.contains(listener))
			doorCollisionListeners.remove(listener);
		logger.warning("removing DoorCollisionListener = " + listener + ", count = [" + doorCollisionListeners.size() + "]");
	}
}
